/**
 *  TextMash - simple IDE for Clojure
 *  
 *  Copyright (C) 2010 Aleksander Naszko
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package pl.olek.textmash.workspace;

import java.awt.Color;

import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

import pl.olek.textmash.matching.OccurrencesMatcher;

/**
 * 
 * @author anaszko
 *
 */
public class ConcurrentDocument extends DefaultStyledDocument implements 
UndoableEditListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = -8192922927997244371L;

	private TextEditor pane;

	private boolean ignoreUndo;

	private Style qlStyle;

	public synchronized StyleContext getStyleContext() {
		return (StyleContext) getAttributeContext();
	}

	public ConcurrentDocument(TextEditor pane) {
		this.pane = pane;
		addUndoableEditListener(this);
		//pane.addUndoableListener(this);
		qlStyle = getStyleContext().addStyle("QuickLookup", null);
		StyleConstants.setBackground(qlStyle, new Color(240, 216, 168));
	}

	public synchronized void clearAllStyle() {
		
//		try {
		
//		SwingUtilities.invokeLater(new Runnable() {
//			public void run() {
				ignoreUndo = true;
				//ConcurrentDocument.this.removeUndoableEditListener(ConcurrentDocument.this);
		
				
				
//				System.out.println("GOT " + getLength());
				setCharacterAttributes(0, getLength(), SimpleAttributeSet.EMPTY, true);
		//ConcurrentDocument.this.addUndoableEditListener(ConcurrentDocument.this);
		ignoreUndo = false;
//			}
//		});
		//ignoreUndo = false;
		//addUndoableEditListener(this);
//		} catch(Exception e) {
//			e.printStackTrace();
//		}
	}

	public synchronized void setStyle(final String name, final int from, final int to) {
		//ignoreUndo = true;
//		removeUndoableEditListener(this);

		//ignoreUndo = false;
//		addUndoableEditListener(this);
		
//		SwingUtilities.invokeLater(new Runnable() {
//			public void run() {
				ignoreUndo = true;
				
				//ConcurrentDocument.this.removeUndoableEditListener(ConcurrentDocument.this);
				setCharacterAttributes(from, to, getStyleContext().getStyle(name),
						false);
				ignoreUndo = false;
		//ConcurrentDocument.this.addUndoableEditListener(ConcurrentDocument.this);
//			}
//		});
	}

	public synchronized boolean isIgnoreUndo() {
		return ignoreUndo;
	}

	public synchronized void setLineEnding(String line) {
		putProperty(DefaultEditorKit.EndOfLineStringProperty, line);
	}

	public synchronized String getLineEnding() {
		Object result = getProperty(DefaultEditorKit.EndOfLineStringProperty);
		if (result == null) {
			return null;
		}
		return result.toString();
	}

//	@Override
//	public void render(Runnable r) {
//		// TODO Auto-generated method stub
//		super.render(r);
//	}

	@Override
	public synchronized void insertString(int offs, String str, AttributeSet a)
			throws BadLocationException {
		OccurrencesMatcher.getInstance().dontDraw = true;
		super.insertString(offs, str, a);
//		if (!ignoreUndo) {
		ignoreUndo = true;
		//removeUndoableEditListener(this);
		MonoTabSet.setTabSize(pane, 4, offs, str.length());
		ignoreUndo = false;
//		}
		//addUndoableEditListener(this);
	}

//	@Override
//	protected void styleChanged(Style style) {
//		// TODO Auto-generated method stub
//		super.styleChanged(style);
//	}

	@Override
	public void remove(int offs, int len) throws BadLocationException {
		// TODO Auto-generated method stub
		OccurrencesMatcher.getInstance().dontDraw = true;
		super.remove(offs, len);
	}

	@Override
	public void replace(int offset, int length, String text, AttributeSet attrs)
			throws BadLocationException {
		// TODO Auto-generated method stub
		OccurrencesMatcher.getInstance().dontDraw = true;
		super.replace(offset, length, text, attrs);
	}

	@Override
	public void undoableEditHappened(UndoableEditEvent e) {
		//System.out.println("here");
		if (!((ConcurrentDocument) e.getSource()).isIgnoreUndo()) {
//			System.out.println("Enetered "+ e.getEdit().getPresentationName());
//			System.out.println("1Can " + pane.undo.canUndoOrRedo());
			if (!pane.undo.addEdit(e.getEdit())) {
				pane.undoAction.updateUndoState();
				pane.redoAction.updateRedoState();
			}
			
			
			
//			System.out.println("Can " + pane.undo.canUndoOrRedo());
		}
	}

}
